package com.project.persistence.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.project.bean.Features;
import com.project.bean.Function;
import com.project.bean.Role;
import com.project.bean.User;
import com.project.persistence.db.Connect;

public class UserDAOImpl extends AbstractDAO<User>{
	
	@Override
	public User getObject(User user) {
		Connect connect = new Connect();
		try {
			
			Connection conn = connect.getConnection();
			PreparedStatement pstm = conn.prepareStatement(getUserQuery());
            pstm.setInt(1, user.getUserId());
            ResultSet rs = pstm.executeQuery();
          
            Role role = user.getRole();
            role.setFeatures(parseListFromRs(rs));
			
            user.setRole(role);
			
		} catch (Exception ex) {
			//TODO acrescentar error no log
			ex.printStackTrace();
		}
		
		return user;
	}
	
	public User getUser(User user) {
		Connect connect = new Connect();
		User userResult = null;
		try {
			Connection conn = connect.getConnection();
			PreparedStatement pstm = conn.prepareStatement(getUserByUsernameQuery());
            pstm.setString(1, user.getUserName());
            ResultSet rs = pstm.executeQuery();
            
            if(rs.next()) {
            	
            	userResult = new User();
            	userResult.setUserId(rs.getInt("id"));
            	userResult.setUserName(rs.getString("username"));
            	userResult.setUserPassword(rs.getString("password"));
            	userResult.setActive(rs.getBoolean("active"));
            	userResult.setRole(new Role(rs.getInt("id_role"), rs.getString("role_name")));
            	
            	userResult = getObject(userResult);
            }
			
		} catch (Exception ex) {
			//TODO acrescentar error no log
			ex.printStackTrace();
		}
		
		return userResult;
	}
	
	
	private List<Features> parseListFromRs(ResultSet rs) throws SQLException {
		List<Features> features = new ArrayList<Features>();
		while(rs.next()) {
			Features f = new Features();
			f.setFeatureId(rs.getInt("id_feature"));
			f.setFeatureName(rs.getString("name"));
			f.setFeatureDescription(rs.getString("description"));
			f.setFeatureLink(rs.getString("link"));
			f.setActive(rs.getBoolean("active"));
			
			List<Function> list = new ArrayList<Function>();
        	
        	for(String func : Arrays.asList(rs.getString("functions").split(","))) {
        		Function function = new Function();
        		function.setName(func);
        		list.add(function);
        	}
        	
        	f.setFunctions(list);
			
			features.add(f);
		}
		
		return features;
	}

	@Override
	public List<User> getAll() {
		Connect connect = new Connect();
		User userResult = null;
		List<User> users = new ArrayList<User>();
		try {
			
			Connection conn = connect.getConnection();
			PreparedStatement pstm = conn.prepareStatement(getAllUsersQuery());
            ResultSet rs = pstm.executeQuery();
			
            while (rs.next()) {
            	
            	userResult = new User();
            	
            	userResult.setUserId(rs.getInt("id"));
            	userResult.setUserName(rs.getString("username"));
            	userResult.setUserPassword(rs.getString("password"));
            	userResult.setActive(rs.getBoolean("active"));
            	userResult.setRole(new Role(rs.getInt("id_role"), rs.getString("role_name")));
            	
            	userResult = getObject(userResult);
            	
            	users.add(userResult);
			}
			
		} catch (Exception ex) {
			//TODO acrescentar error no log
			ex.printStackTrace();
		}
		
		return users;
	}
	
	@Override
	public Boolean disable(User t) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	Boolean enableObject(User user, Connection conn) throws SQLException {
		PreparedStatement pstm = conn.prepareStatement(getEnableDisableQuery());

		pstm.setInt(1, 1);
		pstm.setInt(2, user.getUserId());

		return !pstm.execute();
	}

	@Override
	public User parseObjectFromRs(ResultSet rs) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	List<User> getAllById(Integer id) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	Boolean updateObject(User user, Connection conn) throws SQLException {
		PreparedStatement pstm = conn.prepareStatement(getUpdateQuery());

		pstm.setString(1, user.getUserPassword());
		pstm.setInt(2, user.getRole().getRoleId());
		pstm.setInt(3, user.getUserId());

		return !pstm.execute();
	}

	@Override
	Boolean disableObject(User user, Connection conn) throws SQLException {
		PreparedStatement pstm = conn.prepareStatement(getEnableDisableQuery());

		pstm.setInt(1, 0);
		pstm.setInt(2, user.getUserId());

		return !pstm.execute();
	}

	@Override
	Boolean insertObject(User user, Connection conn) throws SQLException {
		PreparedStatement pstm = conn.prepareStatement(getInsertQuery());

		pstm.setString(1, user.getUserName());
		pstm.setString(2, user.getUserPassword());
		pstm.setInt(3, user.getRole().getRoleId());
		
		return !pstm.execute();
	}
	
	private String getInsertQuery() {
		return "INSERT INTO" +
				" project_database.user (username, password, id_role, active)" +
				" VALUES (?,?,?,1)";
	}
	
	private String getUpdateQuery() {
		return "UPDATE project_database.user" +
				" SET password = ?, id_role = ?" +
				" WHERE id = ?";
	}
	
	private String getUserQuery() {
		return "SELECT"
					+ " u.id id," 
					+ " rf.id_feature," 
					+ " f.name, "
					+ " f.description,"
					+ " f.link,"
					+ " f.functions,"
					+ " f.active"
				+ " FROM "
					+ " project_database.user u," 
					+ " features f, "
					+ " roles_features rf"
				+ " WHERE rf.id_role = u.id_role"
				+ " AND rf.id_feature = f.id"
				+ " AND f.active = 1"
				+ " AND u.id = ?";
	}
	
	private String getUserByUsernameQuery(){
		return "SELECT u.*, r.name role_name FROM project_database.user u, roles r " +
			   " WHERE u.id_role = r.id AND u.username = ?";
	}
	
	private String getAllUsersQuery() {
		return "SELECT u.*, r.name role_name FROM project_database.user u, roles r" + 
			   " WHERE u.id_role = r.id";
	}
	
	private String getEnableDisableQuery() {
		return "UPDATE project_database.user SET active = ? WHERE id = ?";
	}
	
}
